package com.sskj.api.listener;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sskj.api.domain.Device;
import com.sskj.api.enums.DeviceStatusEnum;
import com.sskj.api.service.IDeviceService;
import com.sskj.common.constant.RabbitMQConstant;
import com.sskj.common.dto.DeviceQueueMessage;
import com.sskj.common.dto.motherboard.HeartbeatMessage;
import com.sskj.common.dto.motherboard.OfflineMessage;
import com.sskj.common.dto.motherboard.RegisterMessage;
import com.sskj.common.enums.DeviceMessageTypeEnum;
import com.sskj.common.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.Objects;

@Component
@Slf4j
public class IotMessageListener {

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private IDeviceService deviceService;

    @RabbitListener(queues = RabbitMQConstant.IOT_QUEUE)
    public void iotData(String message) {
//        log.info("消息内容: {}", message);
        processIoData(message);
    }

    /**
     * 处理消息队列中的消息
     * @param message 队列消息
     */
    private void processIoData(String message) {
        try {
            DeviceQueueMessage deviceQueueMessage = objectMapper.readValue(message, DeviceQueueMessage.class);
            if (Objects.equals(deviceQueueMessage.getType(), DeviceMessageTypeEnum.REGISTER.getType())) {
                // 注册信息
                RegisterMessage registerMessage = objectMapper.readValue(deviceQueueMessage.getPayload(), RegisterMessage.class);
                registerHandler(registerMessage);
                // 更新最近登录时间
            } else if (Objects.equals(deviceQueueMessage.getType(), DeviceMessageTypeEnum.HEARTBEAT_CHECK.getType())) {
                // 处理心跳机制
                HeartbeatMessage heartbeatMessage = objectMapper.readValue(deviceQueueMessage.getPayload(), HeartbeatMessage.class);
                heartbeatHandler(heartbeatMessage);
                // 更新心跳最新时间
            } else if (Objects.equals(deviceQueueMessage.getType(), DeviceMessageTypeEnum.OFFLINE.getType())) {
                OfflineMessage offlineMessage = objectMapper.readValue(deviceQueueMessage.getPayload(), OfflineMessage.class);
                offlineMessageHandler(offlineMessage);
            } else {
                log.error("未匹配的对应的消息处理类型。消息内容: {}", message);
            }
            log.info("设备消息: {}", deviceQueueMessage);
        } catch (JsonProcessingException e) {
            log.error("反序列化异常。异常信息: {},内容: {}", e.getMessage(), message);
        }
    }

    /**
     * 设备注册处理
     * @param registerMessage 注册信息
     */
    private void registerHandler(RegisterMessage registerMessage) {
        Device device = deviceService.getByCode(registerMessage.getDeviceId());
        if (device != null) {
            if (device.getActiveTime() == null) {
                device.setActiveTime(LocalDateTime.now());
            }
            if (!StrUtil.isBlank(registerMessage.getVersion())) {
                device.setVersion(registerMessage.getVersion());
            }
            device.setUpdateTime(LocalDateTime.now());
            device.setStatus(DeviceStatusEnum.ONLINE.getStatus());

            deviceService.updateById(device);
        }
    }

    /**
     * 心跳检测处理
     * @param heartbeatMessage 心跳信息
     */
    private void heartbeatHandler(HeartbeatMessage heartbeatMessage) {
        Device device = deviceService.getByCode(heartbeatMessage.getDeviceId());
        if (device != null) {
            device.setLastHeartbeat(heartbeatMessage.getTime());
            device.setUpdateTime(LocalDateTime.now());
            device.setStatus(DeviceStatusEnum.ONLINE.getStatus());

            deviceService.updateById(device);
        }
    }

    /**
     * 离线处理
     * @param offlineMessage 离线信息
     */
    private void offlineMessageHandler(OfflineMessage offlineMessage) {
        Device device = deviceService.getByCode(offlineMessage.getDeviceId());
        if (device != null) {
            device.setStatus(DeviceStatusEnum.OFFLINE.getStatus());
            device.setUpdateTime(LocalDateTime.now());

            deviceService.updateById(device);
        }
    }
}
